#ifndef _VIEW_CHANGE_CERTIFICATE
#define _VIEW_CHANGE_CERTIFICATE 1

#include "../messages/ViewChange.hpp"
#include "../messages/ViewChangeAck.hpp"
#include "../messages/ConfirmView.hpp"

namespace BFT
{
	namespace order
	{
		namespace statemanagement
		{
			//The View change certificate gathers a view change message and the
			//associated pieces required to make it 'valid'.

			//A view change message is valid if either
			//(a) the process verified the view change message itself or
			//(b) the process has a quorum of view change ack messages that
			//validate the view change message		
		
			class ViewChangeCertificate 
			{
				public:
				
				ViewChangeCertificate(uint32_t view, bool primary);
								
				void addAck(boost::shared_ptr<BFT::order::messages::ViewChangeAck> _vca);
				
				void addConfirmView(boost::shared_ptr<BFT::order::messages::ConfirmView> _cv);
				
				bool hasAcks();
				
				void clear();

				void observeViewChange(boost::shared_ptr<BFT::order::messages::ViewChange> _vc); //inlined
				
				boost::shared_ptr<BFT::order::messages::ConfirmView> getConfirmView(); //inlined
				
				boost::shared_ptr<BFT::order::messages::ViewChange> getViewChange(); //inlined
				
				void markFinal(); //inlined
				
				bool isFinal(); //inlined
				
				uint32_t getView(); //inlined
				
				boost::shared_ptr<BFT::messages::Digest> getVCDigest(); //inlined
				
				
				protected:
				
				void addViewChange(boost::shared_ptr<BFT::order::messages::ViewChange> _vc);
				
				boost::shared_ptr<BFT::order::messages::ViewChange> vc;
				std::vector<boost::shared_ptr<BFT::order::messages::ViewChangeAck> > vca;
				std::vector<boost::shared_ptr<BFT::order::messages::ViewChangeAck> > ackCache;
				boost::shared_ptr<BFT::order::messages::ConfirmView> confirmView;
				boost::shared_ptr<BFT::messages::Digest> vcDigest;			
				uint32_t viewNumber;
				bool primary;
				
				private:
				
				bool finished; //to be initialized as false
				bool hasAcksFlag;  //to be initialized as false
			};
			
			inline void ViewChangeCertificate::observeViewChange(boost::shared_ptr<BFT::order::messages::ViewChange> _vc) 
				{ addViewChange(_vc);}
			
			inline boost::shared_ptr<BFT::order::messages::ConfirmView> ViewChangeCertificate::getConfirmView() 
				{return confirmView;}
			
			inline boost::shared_ptr<BFT::order::messages::ViewChange> ViewChangeCertificate::getViewChange() 
				{return vc;}
			
			inline void ViewChangeCertificate::markFinal() {finished = true;}
			
			inline bool ViewChangeCertificate::isFinal() {return finished;}
			
			inline uint32_t ViewChangeCertificate::getView() {return viewNumber;}
			
			inline boost::shared_ptr<BFT::messages::Digest> ViewChangeCertificate::getVCDigest() 
				{return vcDigest;}

		}
	}
}

#endif
